from fastapi import APIRouter, Depends, HTTPException, status, Response, Request
from jose import jwt
from jose.exceptions import JWTError
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from datetime import timedelta
from typing import Optional, Dict, Any
import logging
from ....services.user_service import UserService, Token, TokenData, UserInDB, RefreshTokenRequest
from ....config.settings import settings

# 添加日志器
logger = logging.getLogger(__name__)

router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
user_service = UserService()

@router.post("/login", response_model=Token, tags=["认证管理"])
def login(form_data: OAuth2PasswordRequestForm = Depends()):
    """用户登录，获取访问令牌和刷新令牌"""
    logger.info(f"用户尝试登录: {form_data.username}")
    
    user = user_service.authenticate_user(form_data.username, form_data.password)
    if not user:
        logger.warning(f"用户登录失败: {form_data.username} - 用户名或密码不正确")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户名或密码不正确",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    # 创建访问令牌
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = user_service.create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    
    # 创建刷新令牌
    refresh_token = user_service.create_refresh_token(user.username)
    
    logger.info(f"用户登录成功: {user.username}")
    return {
        "access_token": access_token,
        "refresh_token": refresh_token,
        "token_type": "bearer",
        "expires_in": settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
    }

@router.post("/refresh", response_model=Token, tags=["认证管理"])
def refresh_token(refresh_request: RefreshTokenRequest):
    """使用刷新令牌获取新的访问令牌"""
    username = user_service.verify_refresh_token(refresh_request.refresh_token)
    if not username:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效的刷新令牌",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    # 验证用户是否仍然存在
    user = user_service.get_user_by_username(username)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户不存在",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    # 创建新的访问令牌
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = user_service.create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    # 不想刷新refresh_token，不然要一直更新refresh_token，用户永不退出了
    # 创建新的刷新令牌
    # new_refresh_token = user_service.create_refresh_token(user.username)
    
    # # 撤销旧的刷新令牌
    # user_service.revoke_refresh_token(refresh_request.refresh_token)
    
    logger.info(f"令牌刷新成功: {username}")
    return {
        "access_token": access_token,
        "refresh_token": refresh_request.refresh_token,  # 返回原来的刷新令牌
        "token_type": "bearer",
        "expires_in": settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
    }

@router.get("/token-info", tags=["认证管理"])
def get_token_info(token: str = Depends(oauth2_scheme)):
    """获取当前令牌的过期信息"""
    token_info = user_service.get_token_expiry_info(token)
    if not token_info:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效的令牌"
        )
    
    return token_info

async def get_current_user(token: str = Depends(oauth2_scheme)) -> UserInDB:
    """获取当前登录用户"""
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无法验证凭据",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
        username: str = payload.get("sub")
        token_type: str = payload.get("type", "access")
        
        # 确保是访问令牌
        if token_type != "access":
            logger.warning("尝试使用非访问令牌进行身份验证")
            raise credentials_exception
            
        if username is None:
            logger.warning("JWT令牌中缺少用户名")
            raise credentials_exception
        token_data = TokenData(username=username)
    except JWTError as e:
        logger.warning(f"JWT令牌验证失败: {str(e)}")
        raise credentials_exception
    
    user = user_service.get_user_by_username(username=token_data.username)
    if user is None:
        logger.warning(f"用户不存在: {token_data.username}")
        raise credentials_exception
    return user

async def get_current_user_with_refresh_check(
    request: Request,
    response: Response,
    token: str = Depends(oauth2_scheme)
) -> UserInDB:
    """获取当前用户并检查是否需要自动刷新令牌"""
    user = await get_current_user(token)
    
    # 检查令牌是否即将过期
    token_info = user_service.get_token_expiry_info(token)
    if token_info and token_info.get("should_refresh", False):
        # 在响应头中添加提示，告知前端需要刷新令牌
        response.headers["X-Token-Refresh-Required"] = "true"
        response.headers["X-Token-Remaining-Seconds"] = str(int(token_info.get("remaining_seconds", 0)))
    
    return user

@router.get("/me", response_model=Dict[str, Any], tags=["认证管理"])
def read_users_me(current_user: UserInDB = Depends(get_current_user_with_refresh_check)):
    """获取当前用户信息"""
    logger.debug(f"获取用户信息: {current_user.username}")
    
    # 获取用户的所有权限（角色权限 + 额外权限 + 用户组权限）
    user_permissions = user_service.get_user_permissions(current_user.username)
    user_customs_codes = user_service.get_user_customs_codes(current_user.username)
    
    # 获取角色信息
    from ....services.role_service import RoleService
    role_service = RoleService()
    role = role_service.get_role_by_id(current_user.role_id)
    
    return {
        "username": current_user.username,
        "role_id": current_user.role_id,
        "role_name": role.name if role else "未知角色",
        "is_admin": current_user.role_id == "admin",  # 向后兼容
        "allowed_customs_codes": current_user.allowed_customs_codes,
        "additional_permissions": current_user.additional_permissions,
        "group_ids": current_user.group_ids,
        "effective_permissions": user_permissions,  # 有效权限（角色 + 额外权限）
        "effective_customs_codes": user_customs_codes,  # 有效海关编码（包括用户组权限）
        "created_at": current_user.created_at
    }

@router.post("/logout", tags=["认证管理"])
def logout(
    refresh_request: Optional[RefreshTokenRequest] = None,
    current_user: UserInDB = Depends(get_current_user)
):
    """用户登出，撤销刷新令牌"""
    logger.info(f"用户登出: {current_user.username}")
    
    if refresh_request and refresh_request.refresh_token:
        # 撤销特定的刷新令牌
        user_service.revoke_refresh_token(refresh_request.refresh_token)
    else:
        # 撤销用户的所有刷新令牌
        user_service.revoke_all_user_refresh_tokens(current_user.username)
    
    return {"message": f"用户 {current_user.username} 已成功登出"}

@router.post("/logout-all", tags=["认证管理"])
def logout_all_devices(current_user: UserInDB = Depends(get_current_user)):
    """登出所有设备，撤销用户的所有刷新令牌"""
    logger.info(f"用户登出所有设备: {current_user.username}")
    
    user_service.revoke_all_user_refresh_tokens(current_user.username)
    
    return {"message": f"用户 {current_user.username} 已从所有设备登出"}